﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace FanaticRock.Theme.Helpers
{
    public class ListViewHelper
    {
        private static SizeChangedEventHandler _sizeChangedEventHandler = new SizeChangedEventHandler(ListView_SizeChanged);

        public static string GetColunmDefines(DependencyObject obj)
        {
            return (string)obj.GetValue(ColunmDefinesProperty);
        }

        public static void SetColunmDefines(DependencyObject obj, string value)
        {
            obj.SetValue(ColunmDefinesProperty, value);
        }

        // Using a DependencyProperty as the backing store for ColunmDefines.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColunmDefinesProperty =
            DependencyProperty.RegisterAttached("ColunmDefines", typeof(string), typeof(ListViewHelper), new PropertyMetadata("1*")
            {
                PropertyChangedCallback = (s, e) =>
                {
                    if (s is ListView listView)
                    {
                        UpdateListViewColumn(listView, listView.View as GridView, e.NewValue as string);
                        listView.RemoveHandler(FrameworkElement.SizeChangedEvent, _sizeChangedEventHandler);
                        listView.AddHandler(FrameworkElement.SizeChangedEvent, _sizeChangedEventHandler);
                    }
                }
            });

        private static void ListView_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var listView = sender as ListView;
            if (listView == null) return;

            UpdateListViewColumn(listView, listView.View as GridView, GetColunmDefines(listView));
        }

        ///<summary>更新列表视图的信息。</summary>
        private static void UpdateListViewColumn(ListView listView, GridView gridView, string rawText)
        {
            if (listView == null) return;
            if (gridView == null) return;
            if (string.IsNullOrWhiteSpace(rawText)) return;

            // VisualTreeHelper.GetChild()
            var dp = GetInnerDockPanel(listView);
            var listWidth = dp == null ? listView.ActualWidth : dp.ActualWidth;
            var rawParts = rawText.Split(',');
            var converter = new GridLengthConverter();

            var list = new List<GridLength>();

            foreach (var part in rawParts)
            {
                var gridLength = (GridLength)converter.ConvertFrom(part);
                list.Add(gridLength);
            }

            var gridDefineCount = gridView.Columns.Count;

            var rawCount = list.Count;

            var sameCount = Math.Min(gridDefineCount, rawCount);
            var deltaCount = Math.Abs(gridDefineCount - rawCount);

            var starSum = list.Take(sameCount).Where(i => i.GridUnitType == GridUnitType.Star).Sum(i => i.Value);
            var absSum = list.Take(sameCount).Where(i => i.GridUnitType == GridUnitType.Pixel).Sum(i => i.Value);

            var starWidth = listWidth - absSum;

            for (var i = 0; i < sameCount; i++)
            {
                if (list[i].GridUnitType == GridUnitType.Star)
                {
                    var absWidth = list[i].Value / starSum * starWidth;
                    gridView.Columns[i].Width = absWidth;
                }
                else if (list[i].GridUnitType == GridUnitType.Pixel)
                {
                    var absWidth = list[i].Value;
                    gridView.Columns[i].Width = absWidth;
                }
            }

            if (gridDefineCount > rawCount)
            {
                for (int i = 0; i < gridDefineCount - rawCount; i++)
                {
                    gridView.Columns[i + rawCount].Width = 0;
                }
            }

        }

        private static DockPanel GetInnerDockPanel(ListView listView)
        {
            var bd = VisualTreeHelper.GetChild(listView, 0) as FrameworkElement;
            if (bd == null) return null;
            var sv = VisualTreeHelper.GetChild(bd, 0) as FrameworkElement;
            if (sv == null) return null;
            var gd = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement;
            if (gd == null) return null;
            var dp = VisualTreeHelper.GetChild(gd, 0) as DockPanel;
            if (dp == null) return null;
            return dp;
        }
    }
}
